面试问红黑树,我脸都绿了。。
作者:Sun_TTTT
阅读以下需要了解普通二叉树的插入以及删除操作。
性质一:节点是红色或者是黑色;
在树里面的节点不是红色的就是黑色的,没有其他颜色,要不怎么叫红黑树呢,是吧。
性质二:根节点是黑色;
根节点总是黑色的。它不能为红。
性质三:每个叶节点(NIL或空节点)是黑色;
这个可能有点理解困难,可以看图:
就是连续的两个节点不能是连续的红色,连续的两个节点的意思就是父节点与子节点不能是连续的红色。
性质五:从任一节点到其没个叶节点的所有路径都包含相同数目的黑色节点;
左旋:
右旋:
插入
下面讲讲插入
我们先明确一下各节点的叫法
- 1、当插入的节点是根节点时,直接涂黑即可;
- 2、当要插入的节点的父节点是黑色的时候。
这个时候插入一个红色的节点并没有对这五个性质产生破坏。所以直接插入不用在进行调整操作。
3、如果要插入的节点的父节点是红色且父节点是祖父节点的左支的时候。
这个要分两种情况,一种是叔叔节点为黑的情况,一种是叔叔节点为红的情况。
当叔叔为黑时,也分为两种情况,一种是要插入的节点是父节点的左支,另一种是要插入的节点是父亲的右支。
我们先看一下当要插入的节点是父节点的左支的情况:
这个时候违反了性质四,我们就需要进行调整操作,使之符合性质四,我们可以通过对祖父节点进行右旋同时将祖父节点和父节点的颜色进行互换,这样就变成了:
经过这样的调整可以符合性质四并且不对其他性质产生破坏。
当插入的节点是父节点的右支的时候:
当要插入的节点是父节点的右支的时候,我们可以先对父节点进行左旋,变成如下:
如果我们把原先的父节点看做是新的要插入的节点,把原先要插入的节点看做是新的父节点,那就变成了当要插入的节点在父节点的左支的情况,对,是的,就是按照当要插入的节点在父节点的左支的情况进行旋转,旋转完之后变成如下:
4、如果要插入的节点的父节点是红色且父节点是祖父节点的右支的时候;
这个时候的情况跟情况3所表述的情况是一个镜像,将情况3的左和右互换一下就可以了。
5、如果要插入的节点的父节点是红色并且叔叔节点也为红色,如下:
这个时候,只需将父亲节点和叔叔节点涂黑,将祖父节点涂红。
以上就是插入的全部过程。
删除
首先你要了解普通二叉树的删除操作:
1、如果删除的是叶节点,可以直接删除;
2、如果被删除的元素有一个子节点,可以将子节点直接移到被删除元素的位置;
3、如果有两个子节点,这时候就可以把被删除元素的右支的最小节点(被删除元素右支的最左边的节点)和被删除元素互换,我们把被删除元素右支的最左边的节点称之为后继节点(后继元素),然后在根据情况1或者情况2进行操作。如图:
将被删除元素与其右支的最小元素互换,变成如下图所示:
然后再将被删除元素删除:
变成
如图:
由
变成:
5、当被删除元素为黑、并且为父节点的左支,且兄弟颜色为黑,兄弟的右支为红色,这个时候需要交换兄弟与父亲的颜色,并把父亲涂黑、兄弟的右支涂黑,并以父节点为中心左转。如图:
由:
变成:
6、当被删除元素为黑、并且为父节点的左支,且兄弟颜色为黑,兄弟的左支为红色,这个时候需要先把兄弟与兄弟的左子节点颜色互换,进行右转,然后就变成了规则5一样了,在按照规则5进行旋转。如图:
由
先兄弟与兄弟的左子节点颜色互换,进行右转,变成:
然后在按照规则5进行旋转,变成:
7、当被删除元素为黑且为父元素的右支时,跟情况5.情况6 互为镜像。
8、被删除元素为黑且兄弟节点为黑,兄弟节点的孩子为黑,父亲为黑,这个时候需要将兄弟节点变为红,再把父亲看做那个被删除的元素(只是看做,实际上不删除),看看父亲符和哪一条删除规则,进行处理变化如图:
由:
变成:
9、当被删除的元素为黑,且为父元素的左支,兄弟节点为红色的时候,需要交换兄弟节点与父亲结点的颜色,以父亲结点进行左旋,就变成了情况4,在按照情况四进行操作即可,变化如下:
由:
交换兄弟节点与父亲结点的颜色,以父亲结点进行左旋 变成:
在按照情况四进行操作,变成:
好了,删除的步骤也讲完,没有讲到的一点就是,在添加删除的时候,时刻要记得更改根元素的颜色为黑。
这里并没有语言实现,只是讲了一下红黑树的插入删除步骤,你可以根据步骤自己把红黑树实现。
点击这里,照着规则一步一步的构建一个红黑树吧。
最后
最后的最后的最后,一定要尝试着自己推导一下插入删除规则啊,不然经常忘,是睡一觉起来再看就有点懵逼的那种忘。
1、GitHub 标星 3.2w!史上最全技术人员面试手册!FackBoo发起和总结
5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...